/*
 * Copyright (C) 2024 
 * Licensed under the Apache License, Version 2.0 (the "License");
 */

#include "securec.h"
#include "errcode.h"
#include "osal_addr.h"
#include "sle_common.h"
#include "sle_device_discovery.h"
#include "sle_errcode.h"
#include "sle_ssap_server.h"
#include "sle_connection_manager.h"
#include "sle_device_discovery.h"
#include "SLE_LED_Server_adv.h"
#include "SLE_LED_Server.h"

#include "cmsis_os2.h"
#include "debug_print.h"
#include "soc_osal.h"
#include "app_init.h"
#include "common_def.h"

/* 传感器读取函数（假设使用DHT22传感器） */
#include "dht22.h" // 需要根据实际传感器实现

#define OCTET_BIT_LEN 8
#define UUID_LEN_2 2

#define encode2byte_little(_ptr, data)                     \
    do {                                                   \
        *(uint8_t *)((_ptr) + 1) = (uint8_t)((data) >> 8); \
        *(uint8_t *)(_ptr) = (uint8_t)(data);              \
    } while (0)

/* 服务端UUID和属性UUID定义 */
static char g_sle_uuid_app_uuid[UUID_LEN_2] = {0x0, 0x0};
static char g_sle_property_value[OCTET_BIT_LEN] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};

/* 连接ID和服务句柄 */
static uint16_t g_conn_id = 0;
static uint8_t g_server_id = 0;
static uint16_t g_service_handle = 0;
static uint16_t g_property_handle = 0;

/* 温度和湿度特性句柄 */
static uint16_t g_temp_handle = 0;
static uint16_t g_humidity_handle = 0;

/* 温度和湿度数据 */
static float g_temperature = 0.0;
static float g_humidity = 0.0;

/* 发送通知函数 */
static errcode_t example_sle_server_send_notify_by_handle(const uint8_t *data, uint8_t len);

/**
 * @brief 读取温度和湿度传感器数据
 */
static void read_sensor_data(void)
{
    if (dht22_read(&g_temperature, &g_humidity) != 0) {
        PRINT("[SLE Server] Failed to read sensor data\r\n");
        return;
    }
    PRINT("[SLE Server] Temperature: %.2f°C, Humidity: %.2f%%\r\n", g_temperature, g_humidity);
}

/**
 * @brief 定时任务，定期读取传感器数据并发送通知
 */
static void sensor_read_task(void *arg)
{
    while (1) {
        osal_msleep(2000); // 每2秒读取一次数据
        read_sensor_data();

        /* 将温度和湿度数据打包成通知数据 */
        uint8_t notify_data[8];
        memcpy(notify_data, &g_temperature, sizeof(float));
        memcpy(notify_data + 4, &g_humidity, sizeof(float));

        /* 发送温度和湿度通知 */
        example_sle_server_send_notify_by_handle(notify_data, sizeof(notify_data));
    }
}

/**
 * @brief 添加温度和湿度特性
 */
static errcode_t example_sle_server_add_temp_humidity_characteristics(void)
{
    errcode_t ret = ERRCODE_FAIL;
    sle_uuid_t temp_uuid = {0};
    sle_uuid_t humidity_uuid = {0};

    /* 设置温度特性UUID */
    example_sle_uuid_setu2(0x1123, &temp_uuid);
    ssaps_property_info_t temp_property = {0};
    temp_property.permissions = SSAP_PERMISSION_READ | SSAP_PERMISSION_NOTIFY;
    temp_property.uuid = temp_uuid;
    temp_property.value = osal_vmalloc(sizeof(float));
    if (temp_property.value == NULL) {
        PRINT("[SLE Server] Temperature property mem fail\r\n");
        return ERRCODE_MALLOC;
    }
    memcpy_s(temp_property.value, sizeof(float), &g_temperature, sizeof(float));

    /* 添加温度特性 */
    ret = ssaps_add_property_sync(g_server_id, g_service_handle, &temp_property, &g_temp_handle);
    if (ret != ERRCODE_SUCC) {
        PRINT("[SLE Server] Add temperature property fail, ret:0x%x\r\n", ret);
        osal_vfree(temp_property.value);
        return ERRCODE_FAIL;
    }
    PRINT("[SLE Server] Added temperature characteristic handle: %u\r\n", g_temp_handle);
    osal_vfree(temp_property.value);

    /* 设置湿度特性UUID */
    example_sle_uuid_setu2(0x1124, &humidity_uuid);
    ssaps_property_info_t humidity_property = {0};
    humidity_property.permissions = SSAP_PERMISSION_READ | SSAP_PERMISSION_NOTIFY;
    humidity_property.uuid = humidity_uuid;
    humidity_property.value = osal_vmalloc(sizeof(float));
    if (humidity_property.value == NULL) {
        PRINT("[SLE Server] Humidity property mem fail\r\n");
        return ERRCODE_MALLOC;
    }
    memcpy_s(humidity_property.value, sizeof(float), &g_humidity, sizeof(float));

    /* 添加湿度特性 */
    ret = ssaps_add_property_sync(g_server_id, g_service_handle, &humidity_property, &g_humidity_handle);
    if (ret != ERRCODE_SUCC) {
        PRINT("[SLE Server] Add humidity property fail, ret:0x%x\r\n", ret);
        osal_vfree(humidity_property.value);
        return ERRCODE_FAIL;
    }
    PRINT("[SLE Server] Added humidity characteristic handle: %u\r\n", g_humidity_handle);
    osal_vfree(humidity_property.value);

    return ERRCODE_SUCC;
}

/**
 * @brief 服务器发送通知
 */
static errcode_t example_sle_server_send_notify_by_handle(const uint8_t *data, uint8_t len)
{
    ssaps_ntf_ind_t param = {0};

    /* 发送温度通知 */
    param.handle = g_temp_handle;
    param.type = SSAPS_NOTIFY;
    param.value = osal_vmalloc(len);
    param.value_len = len;
    if (param.value == NULL) {
        PRINT("[SLE Server] Send notify mem fail\r\n");
        return ERRCODE_MALLOC;
    }

    memcpy_s(param.value, param.value_len, data, len);
    if (ssaps_notify_indicate(g_server_id, g_conn_id, &param) != ERRCODE_SUCC) {
        PRINT("[SLE Server] SSAPS notify indicate fail\r\n");
        osal_vfree(param.value);
        return ERRCODE_FAIL;
    }
    osal_vfree(param.value);

    return ERRCODE_SUCC;
}

/* 回调函数实现 */

static void example_ssaps_read_request_cbk(uint8_t server_id,
                                          uint16_t conn_id,
                                          ssaps_req_read_cb_t *read_cb_para,
                                          errcode_t status)
{
    PRINT("[SLE Server] SSAPS read request cbk server_id:0x%x, conn_id:0x%x, handle:0x%x, type:0x%x, status:0x%x\r\n",
          server_id, conn_id, read_cb_para->handle, read_cb_para->type, status);

    /* 根据handle返回相应的值 */
    if (read_cb_para->handle == g_temp_handle) {
        ssaps_read_response_t resp = {0};
        resp.handle = g_temp_handle;
        resp.type = SSAPS_PROPERTY_TYPE_VALUE;
        memcpy_s(resp.value, sizeof(float), &g_temperature, sizeof(float));
        ssaps_read_response(server_id, conn_id, &resp);
    } else if (read_cb_para->handle == g_humidity_handle) {
        ssaps_read_response_t resp = {0};
        resp.handle = g_humidity_handle;
        resp.type = SSAPS_PROPERTY_TYPE_VALUE;
        memcpy_s(resp.value, sizeof(float), &g_humidity, sizeof(float));
        ssaps_read_response(server_id, conn_id, &resp);
    }
}

static void example_ssaps_write_request_cbk(uint8_t server_id,
                                           uint16_t conn_id,
                                           ssaps_req_write_cb_t *write_cb_para,
                                           errcode_t status)
{
    PRINT("[SLE Server] SSAPS write request cbk server_id:0x%x, conn_id:0x%x, handle:0x%x, status:0x%x\r\n",
          server_id, conn_id, write_cb_para->handle, status);

    for (uint16_t idx = 0; idx < write_cb_para->length; idx++) {
        PRINT("[SLE Server] Write request cbk[0x%x] 0x%02x\r\n", idx, write_cb_para->value[idx]);
    }

    /* 处理LED控制指令 */
    // 根据前面的代码，这部分已经在Client端处理
}

static void example_ssaps_mtu_changed_cbk(uint8_t server_id,
                                         uint16_t conn_id,
                                         ssap_exchange_info_t *mtu_size,
                                         errcode_t status)
{
    PRINT("[SLE Server] SSAPS mtu changed cbk server_id:0x%x, conn_id:0x%x, mtu_size:0x%x, status:0x%x\r\n",
          server_id, conn_id, mtu_size->mtu_size, status);
}

static void example_ssaps_start_service_cbk(uint8_t server_id, uint16_t handle, errcode_t status)
{
    PRINT("[SLE Server] Start service cbk server_id:0x%x, handle:0x%x, status:0x%x\r\n",
          server_id, handle, status);
}

/**
 * @brief 注册SSAPS回调函数
 */
static errcode_t example_sle_ssaps_register_cbks(void)
{
    ssaps_callbacks_t ssaps_cbk = {0};
    ssaps_cbk.start_service_cb = example_ssaps_start_service_cbk;
    ssaps_cbk.mtu_changed_cb = example_ssaps_mtu_changed_cbk;
    ssaps_cbk.read_request_cb = example_ssaps_read_request_cbk;
    ssaps_cbk.write_request_cb = example_ssaps_write_request_cbk;
    return ssaps_register_callbacks(&ssaps_cbk);
}

/**
 * @brief 添加服务
 */
static errcode_t example_sle_server_add(void)
{
    errcode_t ret = ERRCODE_FAIL;
    sle_uuid_t app_uuid = {0};

    PRINT("[SLE Server] Add service in\r\n");
    app_uuid.len = sizeof(g_sle_uuid_app_uuid);
    memcpy_s(app_uuid.uuid, app_uuid.len, g_sle_uuid_app_uuid, sizeof(g_sle_uuid_app_uuid));
    ssaps_register_server(&app_uuid, &g_server_id);

    if (ssaps_add_service_sync(g_server_id, &app_uuid, true, &g_service_handle) != ERRCODE_SUCC) {
        PRINT("[SLE Server] Add service fail\r\n");
        ssaps_unregister_server(g_server_id);
        return ERRCODE_FAIL;
    }

    PRINT("[SLE Server] Add service handle: %u\r\n", g_service_handle);

    /* 添加温度和湿度特性 */
    if (example_sle_server_add_temp_humidity_characteristics() != ERRCODE_SUCC) {
        ssaps_unregister_server(g_server_id);
        return ERRCODE_FAIL;
    }

    ret = ssaps_start_service(g_server_id, g_service_handle);
    if (ret != ERRCODE_SUCC) {
        PRINT("[SLE Server] Start service fail, ret:0x%x\r\n", ret);
        return ERRCODE_FAIL;
    }
    PRINT("[SLE Server] Start service out\r\n");
    return ERRCODE_SUCC;
}

/**
 * @brief 初始化广播参数
 */
static errcode_t example_sle_server_adv_init(void)
{
    PRINT("[SLE Server] Initialize advertising\r\n");
    example_sle_set_addr();
    example_sle_set_name();

    if (example_sle_set_default_announce_param() != ERRCODE_SUCC) {
        PRINT("[SLE Server] Set announce param fail\r\n");
        return ERRCODE_FAIL;
    }

    if (example_sle_set_default_announce_data() != ERRCODE_SUCC) {
        PRINT("[SLE Server] Set announce data fail\r\n");
        return ERRCODE_FAIL;
    }

    sle_start_announce(SLE_ADV_HANDLE_DEFAULT);
    PRINT("[SLE Server] Advertising started\r\n");
    return ERRCODE_SUCC;
}

/**
 * @brief 主任务
 */
static int example_sle_led_server_task(const char *arg)
{
    unused(arg);

    osal_msleep(5000); /* 延时5s，等待SLE初始化完毕 */

    PRINT("[SLE Server] Try to enable SLE\r\n");
    /* 使能SLE */
    if (enable_sle() != ERRCODE_SUCC) {
        PRINT("[SLE Server] Enable SLE fail!\r\n");
        return -1;
    }

    /* 注册连接管理回调函数 */
    if (example_sle_conn_register_cbks() != ERRCODE_SUCC) {
        PRINT("[SLE Server] Register connection callbacks fail!\r\n");
        return -1;
    }

    /* 注册 SSAP server 回调函数 */
    if (example_sle_ssaps_register_cbks() != ERRCODE_SUCC) {
        PRINT("[SLE Server] Register SSAPS callbacks fail!\r\n");
        return -1;
    }

    /* 注册Server, 添加Service和property, 启动Service */
    if (example_sle_server_add() != ERRCODE_SUCC) {
        PRINT("[SLE Server] Add server fail!\r\n");
        return -1;
    }

    /* 设置设备公开，并公开设备 */
    if (example_sle_server_adv_init() != ERRCODE_SUCC) {
        PRINT("[SLE Server] Initialize advertising fail!\r\n");
        return -1;
    }

    /* 创建传感器读取任务 */
    osal_task *sensor_task = osal_kthread_create((osal_kthread_handler)sensor_read_task, NULL, "SensorReadTask",
                                                LED_CONTROL_TASK_STACK_SIZE);
    if (sensor_task != NULL) {
        osal_kthread_set_priority(sensor_task, LED_CONTROL_TASK_PRIO);
        osal_kfree(sensor_task);
    }

    PRINT("[SLE Server] Initialization complete\r\n");
    return 0;
}

#define SLE_LED_SER_TASK_PRIO 24
#define SLE_LED_SER_STACK_SIZE 0x2000

static void example_sle_led_server_entry(void)
{
    osal_task *task_handle = NULL;

    osal_kthread_lock();
    task_handle = osal_kthread_create((osal_kthread_handler)example_sle_led_server_task, NULL, "SLELedServerTask",
                                      SLE_LED_SER_STACK_SIZE);
    if (task_handle != NULL) {
        osal_kthread_set_priority(task_handle, SLE_LED_SER_TASK_PRIO);
        osal_kfree(task_handle);
    }
    osal_kthread_unlock();
}

/* 运行服务端入口 */
app_run(example_sle_led_server_entry);
